home *** CD-ROM | disk | FTP | other *** search
- include farnear.inc
-
- BIOS_timer equ 46Ch
-
- _DATA segment byte public 'DATA'
- cnt_suspend dw 0,0
- _DATA ends
-
- _TEXT segment byte public 'CODE'
- assume cs:_TEXT, ds:_DATA
- program _suspend_value
- ; unsigned long suspend_value(unsigned usec)
-
- push bp
- mov bp,sp
- push ds
- mov ax,_DATA
- mov ds,ax
-
- mov ax,cnt_suspend
- or ax,cnt_suspend+2
- ; Was the initialization done?
- jnz short calculate
- xor ax,ax
- mov ds,ax
- ; Test the availability of BIOS timer data
- xor ah,ah
- int 1Ah
- cli
- mov ax,ds:BIOS_timer
- mov bx,ds:BIOS_timer+2
- sti
- ; If the difference > 1
- sub ax,dx
- sbb bx,cx
- jnz short dummy_counter
- shr ax,1
- jz short measure
- ; BIOS timer data unavailable - use dummy value
- dummy_counter:
- mov ax,60000 ; matches α 286/8 MHz
- xor dx,dx
- jmp short store_counter
- ; Measure computer performance for delay calculations
- measure:
- push si
- push di
- xor ax,ax
- mov ds,ax
- xor dx,dx
-
- mov di,ds:BIOS_timer
- wait_tick_over:
- cmp di,ds:BIOS_timer
- je short wait_tick_over
-
- add di,6 ; wait for 5 more ticks
- jmp short loop_condition
- calibrate_loop:
- add ax,1
- adc dx,0 ; increase long
- loop_condition:
- mov cx,si ; begin long comparison
- xor cx,ax
- mov bx,di
- xor bx,dx
- or cx,bx ; finish long comparison
- cmp di,ds:BIOS_timer
- jne short calibrate_loop
- ; The result long number matches to 270272 microseconds
- pop di
- pop si
- store_counter:
- mov bx,_DATA
- mov ds,bx
- mov cnt_suspend,ax
- mov cnt_suspend+2,dx
- calculate:
- ; Get 48-bit multiplication
- mov ax,cnt_suspend
- mul word ptr arglist[0] ; microseconds
- mov bx,ax
- mov cx,dx
- mov ax,cnt_suspend+2
- mul word ptr arglist[0] ; microseconds
- add ax,cx
- adc dx,0 ; DX:AX:BX contains multiplication
- ; Add a half of divisor - arround the result of division
- add bx,4064
- adc ax,2
- adc dx,0
- ; Begin long division - shift by 4 = divide by 16
- mov cx,4
- shift_loop:
- shr dx,1
- rcr ax,1
- rcr bx,1
- loop short shift_loop
- ; Finish long division - divide by 16892
- mov cx,16892
- div cx
- xchg bx,ax
- div cx
- mov dx,bx
- ; DX:AX = (usec * cnt_suspend + uSEC/2) / uSEC
- pop ds
- pop bp
- ret
- _suspend_value endp
-
- program _suspend
- ; void suspend(unsigned long counter)
- push bp
- mov bp,sp
- push si
- push di
- push ds
- mov si,arglist[0] ; counter
- mov di,arglist[2]
- xor ax,ax
- mov ds,ax
- xor dx,dx
- jmp short loop_entry
- delay_loop:
- add ax,1
- adc dx,0 ; increase long
- loop_entry:
- mov cx,si ; begin long comparison
- xor cx,ax
- mov bx,di
- xor bx,dx
- cmp di,ds:BIOS_timer
- or cx,bx ; finish long comparison
- jnz short delay_loop
-
- pop ds
- pop di
- pop si
- pop bp
- ret
- _suspend endp
-
- program _ptr2abs
- ; long ptr2abs(void far *ptr)
- push bp
- mov bp,sp
- mov ax,arglist[0] ; offset
- mov bx,arglist[2] ; segment
- mov cl,4
- mov dx,bx
- shl bx,cl
- rol dx,cl
- xor dx,bx ; clear all save page number
- add ax,bx ; AX = page offset
- adc dx,0 ; DX = page number
- pop bp
- ret
- _ptr2abs endp
-
- program _timer
- ; unsigned long timer(void) - read PC internal timer
- xor ah,ah
- int 1Ah
- mov ax,dx
- mov dx,cx
-
- ; push ds
- ; xor ax,ax
- ; mov ds,ax
- ; lds ax,ds:BIOS_timer
- ; mov dx,ds
- ; pop ds
- ret
- _timer endp
-
- _TEXT ends
- end